package com.hframe.database.plugin;


import com.hframe.data.DRef;
import com.hframe.database.Database;
import com.hframe.database.DatabaseConfig;
import com.hframe.database.SqlFiletr;
import com.hframe.type.*;
import com.hframe.typefilter.*;
import com.hframe.utils.BytesUtils;
import org.apache.log4j.Logger;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.*;
import java.util.Calendar;

/**
 * Created by heqian on 11/21/16.
 */

public class DatabaseMySql extends Database {
    private static Logger log = Logger.getLogger(DatabaseMySql.class);
    private DatabaseConfig config = null;
    private Connection conn = null;
    private Statement statement = null;
    private boolean isCommit = false;

    public DatabaseMySql(DatabaseConfig config) {
        this.config = config;
    }

    @Override
    public DatabaseConfig getConfig() {
        return this.config;
    }

    @Override
    protected boolean getConnection() throws Exception {
        if (null == conn || conn.isClosed()) {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection(config.Url().get() + config.TableName().get() + config.Param().get(), config.UserName().get(), config.UserPass().get());
        }
        return true;
    }

    @Override
    protected boolean createStatement(boolean autoCommit) throws Exception {
        if (null != conn) {
            if (null == statement || statement.isClosed()) {
                setAutoCommit(autoCommit);
                statement = conn.createStatement();
            }
        }
        return true;
    }

    @Override
    protected boolean closeConnection() {
        try {
            if (conn != null) {
                conn.close();
                conn = null;
            }
            return true;
        } catch (Exception e) {
            log.error(e, e);
        }
        return false;
    }

    @Override
    protected boolean closeStatement() {
        try {
            if (statement != null) {
                statement.close();
                statement = null;
            }
        } catch (Exception e) {
            log.error(e, e);
            return false;
        }
        return true;
    }

    @Override
    public void setAutoCommit(boolean paramBoolean) throws Exception {
        if (paramBoolean != conn.getAutoCommit()) {
            conn.setAutoCommit(paramBoolean);
        }
    }

    @Override
    public boolean getAutoCommit() throws Exception {
        return conn.getAutoCommit();
    }

    @Override
    public void commit() throws Exception {
        if (!conn.getAutoCommit())
            conn.commit();
        isCommit = false;
    }

    @Override
    public com.hframe.database.Savepoint setSavepoint() throws Exception {
        com.hframe.database.Savepoint point = new com.hframe.database.Savepoint() {
            private Savepoint point = conn.setSavepoint();

            @Override
            public Object getPoint() {
                return point;
            }
        };

        return point;
    }

    @Override
    public void rollback(com.hframe.database.Savepoint paramSavepoint) throws Exception {
        conn.rollback((Savepoint) paramSavepoint.getPoint());
    }

    @Override
    public void releaseSavepoint(com.hframe.database.Savepoint paramSavepoint) throws Exception {
        conn.releaseSavepoint((Savepoint) paramSavepoint.getPoint());
    }

    @Override
    public void rollback() {
        if (isCommit)
            try {
                if (!conn.getAutoCommit())
                    conn.rollback();
                isCommit = false;
            } catch (SQLException e) {
                log.error(e, e);
            }
    }

    @Override
    protected int execute(String sql) throws Exception {
        try {
            statement.execute(sql);
            isCommit = true;
            return statement.getUpdateCount();
        } catch (Exception e) {
            throw new Exception(e.toString() + " " + sql);
        }
    }

    @Override
    protected int query(String sql, TArray<? extends DRef> datas, int count) throws Exception {
        ResultSet res = null;
        try {
            int index = 0;
            res = statement.executeQuery(sql);
            isCommit = true;
            if (0 != count) {
                while (res.next()) {
                    if (index < count || -2 == count) {
                        DRef object = (DRef) datas.getClassName().newInstance();
                        QueryValue(res, object);
                        datas.addObject(object);
                    }
                    index++;
                }
            }
            return index;

        } catch (Exception e) {
            throw new Exception(e.toString() + " " + sql, e);

        } finally {
            if (null != res)
                res.close();
        }
    }

    private void QueryValue(ResultSet res, DRef<?> object) throws Exception {
        String name;
        T<?> obj;
        int type;
        SqlFiletr filter;
        ResultSetMetaData md = res.getMetaData();
        T<SqlFiletr> outFilter = new T<>();
        int count = md.getColumnCount();

        for (int i = 1; i <= count; i++) {
            if (null == res.getObject(i))
                continue;

            type = md.getColumnType(i);
            if (null == (name = md.getColumnName(i)))
                continue;

            if (null == (obj = FindField(object, name.toLowerCase(), outFilter)))
                continue;

            if (null != (filter = outFilter.get())) {
                if (filter.getReadWait() == SqlFiletr.ReadWait.OnlyRead || filter.getReadWait() == SqlFiletr.ReadWait.NotReadWait)
                    continue;

                setFilterValue(res, type, filter, i);
                continue;
            }

            setValue(res, obj, type, i);
        }

    }

    private void setFilterValue(ResultSet res, int type, SqlFiletr filter, int i) throws Exception {
        switch (type) {
            case Types.INTEGER:
                filter.set(res.getInt(i));
                return;

            case Types.BIT:
                filter.set(res.getBoolean(i));
                return;

            case Types.VARBINARY:
            case Types.LONGVARBINARY:
            case Types.BLOB:
                Blob blob = res.getBlob(i);
                filter.set(blob.getBytes(1, (int) blob.length()));
                return;

            case Types.SMALLINT:
                filter.set(res.getShort(i));
                return;

            case Types.TINYINT:
                filter.set(res.getByte(i));
                return;

            case Types.BIGINT:
                filter.set(res.getLong(i));
                return;

            case Types.LONGVARCHAR:
            case Types.VARCHAR:
            case Types.CHAR:
                filter.set(res.getString(i));
                return;

            case Types.DECIMAL:
                filter.set(res.getBigDecimal(i));
                return;

            case Types.DOUBLE:
                filter.set(res.getDouble(i));
                return;

            case Types.REAL:
            case Types.FLOAT:
                filter.set(res.getFloat(i));
                return;

            case Types.TIME:
                filter.set(res.getTime(i));
                return;

            case Types.TIMESTAMP:
                filter.set(res.getTimestamp(i));
                return;

            case Types.DATE:
                filter.set(res.getDate(i));
                return;
        }
    }

    private void setValue(ResultSet res, T<?> obj, int type, int i) throws SQLException {
        if (obj instanceof TShort) {
            setValueShort(res, (TShort) obj, type, i);

        } else if (obj instanceof TLong) {
            setValueLong(res, (TLong) obj, type, i);

        } else if (obj instanceof TInt) {
            setValueInteger(res, (TInt) obj, type, i);

        } else if (obj instanceof TFloat) {
            setValueFloat(res, (TFloat) obj, type, i);

        } else if (obj instanceof TDouble) {
            setValueDouble(res, (TDouble) obj, type, i);

        } else if (obj instanceof TChar) {
            setValueCharacter(res, (TChar) obj, type, i);

        } else if (obj instanceof TByte) {
            setValueByte(res, (TByte) obj, type, i);

        } else if (obj instanceof TBoolean) {
            setValueBoolean(res, (TBoolean) obj, type, i);

        } else if (obj instanceof TString) {
            setValueString(res, (TString) obj, type, i);

        } else if (obj instanceof TDate) {
            setValueDate(res, (TDate) obj, type, i);

        } else if (obj instanceof TEnum) {
            setValueEnum(res, (TEnum) obj, type, i);

        } else if (obj instanceof TBigDecimal) {
            setValueBigDecimal(res, (TBigDecimal) obj, type, i);

        } else if (obj instanceof TBigInteger) {
            setValueBigInteger(res, (TBigInteger) obj, type, i);

        }

    }

    private void setValueBigInteger(ResultSet res, TBigInteger obj, int type, int i) throws SQLException {
        switch (type) {
            case Types.INTEGER:
                obj.set(BigInteger.valueOf(res.getInt(i)));
                return;

            case Types.BIT:
                obj.set(BigInteger.valueOf(res.getBoolean(i) ? 1 : 0));
                return;

            case Types.VARBINARY:
            case Types.LONGVARBINARY:
            case Types.BLOB:
                obj.set(new BigInteger(res.getBytes(0)));
                return;

            case Types.SMALLINT:
                obj.set(BigInteger.valueOf(res.getShort(i)));
                return;

            case Types.TINYINT:
                obj.set(BigInteger.valueOf(res.getByte(i)));
                return;

            case Types.CHAR:
                try {
                    obj.set(new BigInteger(res.getString(i)));
                } catch (Exception e) {
                    log.error(e.toString(), e);
                }
                return;

            case Types.DECIMAL:
                obj.set(res.getBigDecimal(i).toBigInteger());
                return;

            case Types.DOUBLE:
            case Types.REAL:
            case Types.FLOAT:
                obj.set(BigInteger.valueOf(res.getLong(i)));
                return;

            case Types.TIME:
                obj.set(BigInteger.valueOf(res.getTime(i).getTime()));
                return;

            case Types.TIMESTAMP:
                obj.set(BigInteger.valueOf(res.getTimestamp(i).getTime()));
                return;

            case Types.DATE:
                obj.set(BigInteger.valueOf(res.getDate(i).getTime()));
                return;
        }
    }

    private void setValueBigDecimal(ResultSet res, TBigDecimal obj, int type, int i) throws SQLException {
        switch (type) {
            case Types.INTEGER:
                obj.set(new BigDecimal(res.getInt(i)));
                return;

            case Types.BIT:
                obj.set(new BigDecimal(res.getBoolean(i) ? 1 : 0));
                return;

            case Types.VARBINARY:
            case Types.LONGVARBINARY:
            case Types.BLOB:
                byte[] bytes = res.getBytes(0);
                byte[] longbytes = {bytes.length > 0 ? bytes[0] : 0,
                        bytes.length > 1 ? bytes[1] : 0,
                        bytes.length > 2 ? bytes[2] : 0,
                        bytes.length > 3 ? bytes[3] : 0,
                        bytes.length > 4 ? bytes[4] : 0,
                        bytes.length > 5 ? bytes[5] : 0,
                        bytes.length > 6 ? bytes[6] : 0,
                        bytes.length > 7 ? bytes[7] : 0};

                obj.set(new BigDecimal(BytesUtils.getLong(longbytes)));
                return;

            case Types.SMALLINT:
                obj.set(new BigDecimal(res.getShort(i)));
                return;

            case Types.TINYINT:
                obj.set(new BigDecimal(res.getByte(i)));
                return;

            case Types.BIGINT:
                obj.set(new BigDecimal(res.getLong(i)));
                return;

            case Types.LONGVARCHAR:
            case Types.VARCHAR:
            case Types.CHAR:
                obj.set(new BigDecimal(res.getString(i)));
                return;

            case Types.DECIMAL:
                obj.set(res.getBigDecimal(i));
                return;

            case Types.DOUBLE:
                obj.set(new BigDecimal(res.getDouble(i)));
                return;

            case Types.REAL:
            case Types.FLOAT:
                obj.set(new BigDecimal(res.getFloat(i)));
                return;

            case Types.TIME:
                obj.set(new BigDecimal(res.getTime(i).getTime()));
                return;

            case Types.TIMESTAMP:
                obj.set(new BigDecimal(res.getTimestamp(i).getTime()));
                return;

            case Types.DATE:
                obj.set(new BigDecimal(res.getDate(i).getTime()));
                return;
        }
    }

    private void setValueDate(ResultSet res, TDate obj, int type, int i) throws SQLException {
        long time = 0;
        switch (type) {
            case Types.INTEGER:
                time = (long) res.getInt(i);
                break;

            case Types.BIT:
                time = (long) (res.getBoolean(i) ? 1 : 0);
                break;

            case Types.VARBINARY:
            case Types.LONGVARBINARY:
            case Types.BLOB:
                Blob blob = res.getBlob(i);
                byte[] bytes = res.getBytes(0);
                byte[] longbytes = {bytes.length > 0 ? bytes[0] : 0,
                        bytes.length > 1 ? bytes[1] : 0,
                        bytes.length > 2 ? bytes[2] : 0,
                        bytes.length > 3 ? bytes[3] : 0,
                        bytes.length > 4 ? bytes[4] : 0,
                        bytes.length > 5 ? bytes[5] : 0,
                        bytes.length > 6 ? bytes[6] : 0,
                        bytes.length > 7 ? bytes[7] : 0};

                time = BytesUtils.getLong(longbytes);
                break;

            case Types.SMALLINT:
                time = (long) res.getShort(i);
                break;

            case Types.TINYINT:
                time = (long) res.getByte(i);
                break;

            case Types.BIGINT:
                time = res.getLong(i);
                break;

            case Types.LONGVARCHAR:
            case Types.VARCHAR:
            case Types.CHAR:
                time = StringToLong.parse(res.getString(i));
                break;

            case Types.DECIMAL:
            case Types.DOUBLE:
                time = (long) res.getDouble(i);
                break;

            case Types.REAL:
            case Types.FLOAT:
                time = (long) res.getFloat(i);
                break;

            case Types.TIME:
                time = res.getTime(i).getTime();
                break;

            case Types.TIMESTAMP:
                time = res.getTimestamp(i).getTime();
                break;

            case Types.DATE:
                time = res.getDate(i).getTime();
                break;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(time);
        obj.set(cal.getTime());
    }

    private void setValueString(ResultSet res, TString obj, int type, int i) throws SQLException {
        switch (type) {
            case Types.INTEGER:
                obj.set("" + res.getInt(i));
                return;

            case Types.BIT:
                obj.set("" + res.getBoolean(i));
                return;

            case Types.VARBINARY:
            case Types.LONGVARBINARY:
            case Types.BLOB:
                Blob blob = res.getBlob(i);
                byte[] bytes = res.getBytes(0);
                obj.set(new String(bytes));
                return;

            case Types.SMALLINT:
                obj.set("" + res.getShort(i));
                return;

            case Types.TINYINT:
                obj.set("" + res.getByte(i));
                return;

            case Types.BIGINT:
                obj.set("" + res.getLong(i));
                return;

            case Types.LONGVARCHAR:
            case Types.VARCHAR:
            case Types.CHAR:
                obj.set(res.getString(i));
                return;

            case Types.DECIMAL:
            case Types.DOUBLE:
                obj.set("" + res.getDouble(i));
                return;

            case Types.REAL:
            case Types.FLOAT:
                obj.set("" + res.getFloat(i));
                return;

            case Types.TIME:
                obj.set("" + res.getTime(i).getTime());
                return;

            case Types.TIMESTAMP:
                obj.set("" + res.getTimestamp(i).getTime());
                return;

            case Types.DATE:
                obj.set("" + res.getDate(i).getTime());
                return;
        }
    }

    private void setValueBoolean(ResultSet res, TBoolean obj, int type, int i) throws SQLException {
        switch (type) {
            case Types.INTEGER:
                obj.set(0 != res.getInt(i));
                return;

            case Types.BIT:
                obj.set(res.getBoolean(i));
                return;

            case Types.VARBINARY:
            case Types.LONGVARBINARY:
            case Types.BLOB:
                Blob blob = res.getBlob(i);
                byte[] bytes = res.getBytes(0);


                obj.set(bytes.length > 0 ? 0 != bytes[0] : false);
                return;

            case Types.SMALLINT:
                obj.set(0 != res.getShort(i));
                return;

            case Types.TINYINT:
                obj.set(0 != res.getByte(i));
                return;

            case Types.BIGINT:
                obj.set(0 != res.getLong(i));
                return;

            case Types.LONGVARCHAR:
            case Types.VARCHAR:
            case Types.CHAR:
                obj.set(StringToBoolean.parse(res.getString(i)));
                return;

            case Types.DECIMAL:
            case Types.DOUBLE:
                obj.set(0 != res.getDouble(i));
                return;

            case Types.REAL:
            case Types.FLOAT:
                obj.set(0 != res.getFloat(i));
                return;

            case Types.TIME:
                obj.set(0 != res.getTime(i).getTime());
                return;

            case Types.TIMESTAMP:
                obj.set(0 != res.getTimestamp(i).getTime());
                return;

            case Types.DATE:
                obj.set(0 != res.getDate(i).getTime());
                return;
        }
    }

    private void setValueByte(ResultSet res, TByte obj, int type, int i) throws SQLException {
        switch (type) {
            case Types.INTEGER:
                obj.set((byte) res.getInt(i));
                return;

            case Types.BIT:
                obj.set((byte) (res.getBoolean(i) ? 1 : 0));
                return;

            case Types.VARBINARY:
            case Types.LONGVARBINARY:
            case Types.BLOB:
                Blob blob = res.getBlob(i);
                byte[] bytes = res.getBytes(0);


                obj.set(bytes.length > 0 ? bytes[0] : 0);
                return;

            case Types.SMALLINT:
                obj.set((byte) res.getShort(i));
                return;

            case Types.TINYINT:
                obj.set((byte) res.getByte(i));
                return;

            case Types.BIGINT:
                obj.set((byte) res.getLong(i));
                return;

            case Types.LONGVARCHAR:
            case Types.VARCHAR:
            case Types.CHAR:
                obj.set(StringToByte.parse(res.getString(i)));
                return;

            case Types.DECIMAL:
            case Types.DOUBLE:
                obj.set((byte) res.getDouble(i));
                return;

            case Types.REAL:
            case Types.FLOAT:
                obj.set((byte) res.getFloat(i));
                return;

            case Types.TIME:
                obj.set((byte) res.getTime(i).getTime());
                return;

            case Types.TIMESTAMP:
                obj.set((byte) res.getTimestamp(i).getTime());
                return;

            case Types.DATE:
                obj.set((byte) res.getDate(i).getTime());
                return;
        }
    }

    private void setValueCharacter(ResultSet res, TChar obj, int type, int i) throws SQLException {
        switch (type) {
            case Types.INTEGER:
                obj.set((char) res.getInt(i));
                return;

            case Types.BIT:
                obj.set((char) (res.getBoolean(i) ? 1 : 0));
                return;

            case Types.VARBINARY:
            case Types.LONGVARBINARY:
            case Types.BLOB:
                Blob blob = res.getBlob(i);
                byte[] bytes = res.getBytes(0);


                obj.set(bytes.length > 0 ? (char) bytes[0] : 0);
                return;

            case Types.SMALLINT:
                obj.set((char) res.getShort(i));
                return;

            case Types.TINYINT:
                obj.set((char) res.getByte(i));
                return;

            case Types.BIGINT:
                obj.set((char) res.getLong(i));
                return;

            case Types.LONGVARCHAR:
            case Types.VARCHAR:
            case Types.CHAR:
                obj.set(StringToCharacter.parse(res.getString(i)));
                return;

            case Types.DECIMAL:
            case Types.DOUBLE:
                obj.set((char) res.getDouble(i));
                return;

            case Types.REAL:
            case Types.FLOAT:
                obj.set((char) res.getFloat(i));
                return;

            case Types.TIME:
                obj.set((char) res.getTime(i).getTime());
                return;

            case Types.TIMESTAMP:
                obj.set((char) res.getTimestamp(i).getTime());
                return;

            case Types.DATE:
                obj.set((char) res.getDate(i).getTime());
                return;
        }
    }

    @Override
    protected void addColumnName(StringBuffer strSql, boolean b) {
        if (b)
            strSql.append("`");
        else
            strSql.append("`");
    }

    private void setValueDouble(ResultSet res, TDouble obj, int type, int i) throws SQLException {
        switch (type) {
            case Types.INTEGER:
                obj.set((double) res.getInt(i));
                return;

            case Types.BIT:
                obj.set((double) (res.getBoolean(i) ? 1 : 0));
                return;

            case Types.VARBINARY:
            case Types.LONGVARBINARY:
            case Types.BLOB:
                Blob blob = res.getBlob(i);
                byte[] bytes = res.getBytes(0);
                byte[] doublebytes = {bytes.length > 0 ? bytes[0] : 0,
                        bytes.length > 1 ? bytes[1] : 0,
                        bytes.length > 2 ? bytes[2] : 0,
                        bytes.length > 3 ? bytes[3] : 0,
                        bytes.length > 4 ? bytes[4] : 0,
                        bytes.length > 5 ? bytes[5] : 0,
                        bytes.length > 6 ? bytes[6] : 0,
                        bytes.length > 7 ? bytes[7] : 0};

                obj.set(BytesUtils.getDouble(doublebytes));
                return;

            case Types.SMALLINT:
                obj.set((double) res.getShort(i));
                return;

            case Types.TINYINT:
                obj.set((double) res.getByte(i));
                return;

            case Types.BIGINT:
                obj.set((double) res.getLong(i));
                return;

            case Types.LONGVARCHAR:
            case Types.VARCHAR:
            case Types.CHAR:
                obj.set(StringToDouble.parse(res.getString(i)));
                return;

            case Types.DECIMAL:
            case Types.DOUBLE:
                obj.set(res.getDouble(i));
                return;

            case Types.REAL:
            case Types.FLOAT:
                obj.set((double) res.getFloat(i));
                return;

            case Types.TIME:
                obj.set((double) res.getTime(i).getTime());
                return;

            case Types.TIMESTAMP:
                obj.set((double) res.getTimestamp(i).getTime());
                return;

            case Types.DATE:
                obj.set((double) res.getDate(i).getTime());
                return;
        }
    }

    private void setValueFloat(ResultSet res, TFloat obj, int type, int i) throws SQLException {
        switch (type) {
            case Types.INTEGER:
                obj.set((float) res.getInt(i));
                return;

            case Types.BIT:
                obj.set((float) (res.getBoolean(i) ? 1 : 0));
                return;

            case Types.VARBINARY:
            case Types.LONGVARBINARY:
            case Types.BLOB:
                Blob blob = res.getBlob(i);
                byte[] bytes = res.getBytes(0);
                byte[] floatbytes = {bytes.length > 0 ? bytes[0] : 0,
                        bytes.length > 1 ? bytes[1] : 0,
                        bytes.length > 2 ? bytes[2] : 0,
                        bytes.length > 3 ? bytes[3] : 0};

                obj.set(BytesUtils.getFloat(floatbytes));
                return;

            case Types.SMALLINT:
                obj.set((float) res.getShort(i));
                return;

            case Types.TINYINT:
                obj.set((float) res.getByte(i));
                return;

            case Types.BIGINT:
                obj.set((float) res.getLong(i));
                return;

            case Types.LONGVARCHAR:
            case Types.VARCHAR:
            case Types.CHAR:
                obj.set(StringToFloat.parse(res.getString(i)));
                return;

            case Types.DECIMAL:
            case Types.DOUBLE:
                obj.set((float) res.getDouble(i));
                return;

            case Types.REAL:
            case Types.FLOAT:
                obj.set((float) res.getFloat(i));
                return;

            case Types.TIME:
                obj.set((float) res.getTime(i).getTime());
                return;

            case Types.TIMESTAMP:
                obj.set((float) res.getTimestamp(i).getTime());
                return;

            case Types.DATE:
                obj.set((float) res.getDate(i).getTime());
                return;
        }
    }

    private void setValueInteger(ResultSet res, TInt obj, int type, int i) throws SQLException {
        switch (type) {
            case Types.INTEGER:
                obj.set(res.getInt(i));
                return;

            case Types.BIT:
                obj.set((int) (res.getBoolean(i) ? 1 : 0));
                return;

            case Types.VARBINARY:
            case Types.LONGVARBINARY:
            case Types.BLOB:
                Blob blob = res.getBlob(i);
                byte[] bytes = res.getBytes(0);
                byte[] shortbytes = {bytes.length > 0 ? bytes[0] : 0,
                        bytes.length > 1 ? bytes[1] : 0,
                        bytes.length > 2 ? bytes[2] : 0,
                        bytes.length > 3 ? bytes[3] : 0};

                obj.set(BytesUtils.getInt(shortbytes));
                return;

            case Types.SMALLINT:
                obj.set((int) res.getShort(i));
                return;

            case Types.TINYINT:
                obj.set((int) res.getByte(i));
                return;

            case Types.BIGINT:
                obj.set((int) res.getLong(i));
                return;

            case Types.LONGVARCHAR:
            case Types.VARCHAR:
            case Types.CHAR:
                obj.set(StringToInteger.parse(res.getString(i)));
                return;

            case Types.DECIMAL:
            case Types.DOUBLE:
                obj.set((int) res.getDouble(i));
                return;

            case Types.REAL:
            case Types.FLOAT:
                obj.set((int) res.getFloat(i));
                return;

            case Types.TIME:
                obj.set((int) res.getTime(i).getTime());
                return;

            case Types.TIMESTAMP:
                obj.set((int) res.getTimestamp(i).getTime());
                return;

            case Types.DATE:
                obj.set((int) res.getDate(i).getTime());
                return;
        }
    }

    private void setValueLong(ResultSet res, TLong obj, int type, int i) throws SQLException {
        switch (type) {
            case Types.INTEGER:
                obj.set((long) res.getInt(i));
                return;

            case Types.BIT:
                obj.set((long) (res.getBoolean(i) ? 1 : 0));
                return;

            case Types.VARBINARY:
            case Types.LONGVARBINARY:
            case Types.BLOB:
                Blob blob = res.getBlob(i);
                byte[] bytes = res.getBytes(0);
                byte[] longbytes = {bytes.length > 0 ? bytes[0] : 0,
                        bytes.length > 1 ? bytes[1] : 0,
                        bytes.length > 2 ? bytes[2] : 0,
                        bytes.length > 3 ? bytes[3] : 0,
                        bytes.length > 4 ? bytes[4] : 0,
                        bytes.length > 5 ? bytes[5] : 0,
                        bytes.length > 6 ? bytes[6] : 0,
                        bytes.length > 7 ? bytes[7] : 0};

                obj.set(BytesUtils.getLong(longbytes));
                return;

            case Types.SMALLINT:
                obj.set((long) res.getShort(i));
                return;

            case Types.TINYINT:
                obj.set((long) res.getByte(i));
                return;

            case Types.BIGINT:
                obj.set(res.getLong(i));
                return;

            case Types.LONGVARCHAR:
            case Types.VARCHAR:
            case Types.CHAR:
                obj.set(StringToLong.parse(res.getString(i)));
                return;

            case Types.DECIMAL:
            case Types.DOUBLE:
                obj.set((long) res.getDouble(i));
                return;

            case Types.REAL:
            case Types.FLOAT:
                obj.set((long) res.getFloat(i));
                return;

            case Types.TIME:
                obj.set(res.getTime(i).getTime());
                return;

            case Types.TIMESTAMP:
                obj.set(res.getTimestamp(i).getTime());
                return;

            case Types.DATE:
                obj.set(res.getDate(i).getTime());
                return;
        }
    }

    private void setValueShort(ResultSet res, TShort obj, int type, int i) throws SQLException {
        switch (type) {
            case Types.INTEGER:
                obj.set((short) res.getInt(i));
                return;

            case Types.BIT:
                obj.set((short) (res.getBoolean(i) ? 1 : 0));
                return;

            case Types.VARBINARY:
            case Types.LONGVARBINARY:
            case Types.BLOB:
                Blob blob = res.getBlob(i);
                byte[] bytes = res.getBytes(0);
                byte[] shortbytes = {bytes.length > 0 ? bytes[0] : 0
                        , bytes.length > 1 ? bytes[1] : 0};
                obj.set(BytesUtils.getShort(shortbytes));
                return;

            case Types.SMALLINT:
                obj.set(res.getShort(i));
                return;

            case Types.TINYINT:
                obj.set((short) res.getByte(i));
                return;

            case Types.BIGINT:
                obj.set((short) res.getLong(i));
                return;

            case Types.LONGVARCHAR:
            case Types.VARCHAR:
            case Types.CHAR:
                obj.set(StringToShort.parse(res.getString(i)));
                return;

            case Types.DECIMAL:
            case Types.DOUBLE:
                obj.set((short) res.getDouble(i));
                return;

            case Types.REAL:
            case Types.FLOAT:
                obj.set((short) res.getFloat(i));
                return;

            case Types.TIME:
                obj.set((short) res.getTime(i).getTime());
                return;

            case Types.TIMESTAMP:
                obj.set((short) res.getTimestamp(i).getTime());
                return;

            case Types.DATE:
                obj.set((short) res.getDate(i).getTime());
                return;
        }
    }


    private void setValueEnum(ResultSet res, TEnum obj, int type, int i) throws SQLException {
        switch (type) {
            case Types.INTEGER:
                setEnumValue(obj, res.getInt(i));
                return;

            case Types.BIT:
                setEnumValue(obj, (int) (res.getBoolean(i) ? 1 : 0));
                return;

            case Types.VARBINARY:
            case Types.LONGVARBINARY:
            case Types.BLOB:
                Blob blob = res.getBlob(i);
                byte[] bytes = res.getBytes(0);
                byte[] shortbytes = {bytes.length > 0 ? bytes[0] : 0,
                        bytes.length > 1 ? bytes[1] : 0,
                        bytes.length > 2 ? bytes[2] : 0,
                        bytes.length > 3 ? bytes[3] : 0};

                setEnumValue(obj, BytesUtils.getInt(shortbytes));
                return;

            case Types.SMALLINT:
                setEnumValue(obj, (int) res.getShort(i));
                return;

            case Types.TINYINT:
                setEnumValue(obj, (int) res.getByte(i));
                return;

            case Types.BIGINT:
                setEnumValue(obj, (int) res.getLong(i));
                return;

            case Types.LONGVARCHAR:
            case Types.VARCHAR:
            case Types.CHAR:
                setEnumValue(obj, StringToInteger.parse(res.getString(i)));
                return;

            case Types.DECIMAL:
            case Types.DOUBLE:
                setEnumValue(obj, (int) res.getDouble(i));
                return;

            case Types.REAL:
            case Types.FLOAT:
                setEnumValue(obj, (int) res.getFloat(i));
                return;

            case Types.TIME:
                setEnumValue(obj, (int) res.getTime(i).getTime());
                return;

            case Types.TIMESTAMP:
                setEnumValue(obj, (int) res.getTimestamp(i).getTime());
                return;

            case Types.DATE:
                setEnumValue(obj, (int) res.getDate(i).getTime());
                return;
        }
    }
}
